﻿using System;
using System.Data;
using System.Linq;
using Newtonsoft.Json;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Base.Entity;
using Dapper;
using System.Data.SqlClient;
using T.FAS.Runtime.DataModel.Plugin;
using T.FAS.Runtime.DataAccess.SQLDom;
using T.ServiceComponent.Config.Client;
using System.Collections.Generic;
using T.ServiceComponent.Common.Service;

namespace T.FAS.Runtime.DataAccess.UnitTest
{
    public class DACLocalTestTool
    {
        static DataObjectRTPManager _doRTPManager = new DataObjectRTPManager();
        static CompositeDataObjectRTPManager _cdoRTPManager = new CompositeDataObjectRTPManager();

        public static T GetMetaDataLocal<T>(string metaDataID, string path = "PresetData\\MetaJson\\主子三层")
		{
			var curPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path, $"{metaDataID}.json");
            if (!File.Exists(curPath))
                throw new Exception($"文件:{curPath}不存在");
			var content = File.ReadAllText(curPath);
            T obj = JsonConvert.DeserializeObject<T>(content);
			return obj;
        }

        public static T GetMetaData<T>(string metaDataID) where T : AbsMetaDataContent
        {
            if (typeof(T) == typeof(CompositeDataObject))
            {
                CompositeDataObject cdo = _cdoRTPManager.GetMetaDataContent(metaDataID) as CompositeDataObject;
                PackagingDependencyMetaData(cdo, true);
                return cdo as T;
            }
            return default(T);
        }

        public static string GetPresetDataSQLs(string path = "PresetData\\MetaJson\\主子三层")
		{
            var curPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path, $"data.sql");
            if (!File.Exists(curPath))
                throw new Exception($"文件:{curPath}不存在");
            var content = File.ReadAllText(curPath);
			return content;
        }

		public static void ExecPresetSQL()
		{
			var sqls = GetPresetDataSQLs();
            using (IDbConnection db = new SqlConnection("Database=TFAS_BUTest;Server=127.0.0.1,1433;User ID=root;Password=123456;"))
			{
				db.Execute(sqls);
            }
        }

        public static void ExecPresetSQL(string sqls)
        {
            //cc环境sqlserver
            using (IDbConnection db = new SqlConnection("Database=ttest_sql;Server=127.0.0.1,1433;User ID=sa;Password=123456;"))
            {
                db.Execute(sqls);
            }
        }

        public static void PackagingDependencyMetaData(CompositeDataObject metaData, bool isGetFromDB = false)
        {
            var cdo = metaData;
            if (cdo == null)
                return;
            var unifyCode = DataModelErrorCode.GetUnifiedErrorCode(metaData?.ID, cdo.ID, cdo.Code);
            try
            {
                //当CDO的Nodes节点为空时，从DB中拉取完整CDO元数据
                if (cdo.CompositeNodeObjects == null || cdo.CompositeNodeObjects.Count == 0)
                    throw new FasException(DataModelErrorCode.CDO.InitError, $"{cdo.Code}元数据信息不完整");
                cdo.RootCompositeNodeObject = cdo.CompositeNodeObjects.Find(cno => cno.IsRootObject);
                foreach (var cno in cdo.CompositeNodeObjects)
                {
                    if (cno.DataObject == null)
                    {
                        if (isGetFromDB)
                            cno.DataObject = _doRTPManager.GetMetaDataContent(cno.DataObjectID) as DataObject;
                        else
                            cno.DataObject = GetMetaDataLocal<DataObject>(cno.DataObjectID);
                    }
                    if (cno.DataObject?.Database == null && cno.DataObject != null)
                        cno.DataObject.Database = null;
                    var outerAssos = cno.Associations.Where(o => o.AssociateType == AssociateType.OuterLeftJoin).ToList();
                    var refeles = outerAssos.SelectMany(outer => outer.RefElements).ToList();
                    //初始化Element对应的DataColumn属性
                    if (cno.Elements != null && cno.Elements.Count > 0)
                    {
                        foreach (var ele in cno.Elements)
                        {
                            if (ele.ElementType == ElementType.Normal)   //初始化所有Normal Element对应的DataColumn对象
                            {
                                ele.DataColumn = cno.DataObject.Columns.Find(col => col.ID == ele.DataColumnID);
                            }
                        }
                    }
                    cno.ChildCompositeNodeObjects = cdo.CompositeNodeObjects
                                                        .Where(o => o.ParentObjectID == cno.ID)
                                                        .OrderBy(o => o.ID)
                                                        .ToList();
                    cno.ChildCompositeNodeObjects.ForEach(child => child.ParentObject = cno);
                    //构造关联关系实体引用
                    if (cno.Associations != null && cno.Associations.Count > 0)
                    {
                        foreach (var asso in cno.Associations)
                        {
                            if (asso.AssociateType == AssociateType.InnerJoin)
                            {
                                asso.AssoDomaiModel = cdo;
                                asso.AssoCompositeNodeObject = cdo.CompositeNodeObjects.Find(o => o.ID == asso.AssoCompositeNodeObjectID);
                            }
                            else if (asso.AssociateType == AssociateType.OuterLeftJoin)
                            {

                                if (isGetFromDB)
                                    asso.AssoDataObject = _doRTPManager.GetMetaDataContent(asso.AssoDataObjectID) as DataObject;
                                else
                                    asso.AssoDataObject = GetMetaDataLocal<DataObject>(asso.AssoDataObjectID);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}数据组装失败，请检查！", e);
            }
        }

        public static void PackagingDependencyMetaData(DataQuery metaData)
        {
            InitializeDQ(metaData);
        }

        /// <summary>
        /// 初始化填充DQ的引用类型属性
        /// </summary>
        /// <param name="dataquery"></param>
        public static void InitializeDQ(DataQuery dataquery, bool isSubQuery = false, bool isGetFromDB = false)
        {
            if (dataquery == null)
                return;
            var unifyCode = DataModelErrorCode.GetUnifiedErrorCode(dataquery.Code, dataquery.ID, dataquery.Code);
            try
            {
                //为datasource填充DO实例
                foreach (var source in dataquery.DataQuerySources)
                {
                    if (source.DataObject == null)
                    {
                        if (isGetFromDB)
                            source.DataObject = _doRTPManager.GetMetaDataContent(source.DataObjectID) as DataObject;
                        else
                            source.DataObject = GetMetaDataLocal<DataObject>(source.DataObjectID);
                    }

                    if (source.DataObject == null)
                        throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}获取dataObject:{source.DataObjectID}实体失败，请检查！");
                }
                var dqSources = dataquery.DataQuerySources.Select(s => s.DataObject).ToList();
                //为datacolumn填充实例
                foreach (var column in dataquery.DataQueryColumns)
                {
                    if (column.ColumnType == ColumnType.Normal)
                    {
                        column.DataObject = dqSources.Find(o => o.ID == column.DataObjectID);
                        column.DataColumn = column.DataObject.Columns.Find(col => col.ID == column.DataObjectColumnID);

                    }
                    else
                    {
                        //聚合列也需要填充DO及列信息
                        if (!string.IsNullOrEmpty(column.DataObjectID))
                        {
                            column.DataObject = dqSources.Find(o => o.ID == column.DataObjectID);
                            column.DataColumn = column.DataObject.Columns.Find(col => col.ID == column.DataObjectColumnID);
                            if (column.DataColumn == null)
                                throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}获取dataObject:{column.DataObject.Code}的列:{column.DataObjectColumnID}失败，请检查！");
                        }
                    }
                    if (!string.IsNullOrEmpty(column.DataObjectID))
                    {
                        if (column.DataObject == null)
                        {
                            throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}的列:{column.Name}获取dataObject实体失败，请检查！");
                        }
                    }
                }
                //为datasort填充实例
                if (dataquery.DataQuerySorts != null)
                {
                    foreach (var sort in dataquery.DataQuerySorts.Where(s => s.SortItemType == 0))
                    {
                        //如何判断sort列为自定义列，当SortItemType：0 且 DataObjectID为空时
                        if (!string.IsNullOrEmpty(sort.DataObjectID))
                        {
                            sort.DataObject = dqSources.Find(o => o.ID == sort.DataObjectID);
                            sort.DataColumn = sort.DataObject.Columns.Find(col => col.ID == sort.DataObjectColumnID);
                        }
                        else if (!string.IsNullOrEmpty(sort.DataQueryColumnID))
                        {
                            sort.DataQueryColumn = dataquery.DataQueryColumns.Find(c => c.ID == sort.DataQueryColumnID);
                        }
                    }
                }
                //填充Join实例
                if (dataquery.DataQueryJoins != null)
                {
                    foreach (var join in dataquery.DataQueryJoins)
                    {
                        join.LeftQuerySource = dataquery.DataQuerySources.Find(s => s.ID == join.LeftSourceID);
                        join.RightQuerySource = dataquery.DataQuerySources.Find(s => s.ID == join.RightSourceID);
                    }
                }
                if (dataquery.SubQuerys != null)
                {
                    //填充subquery实例
                    foreach (var subquery in dataquery.SubQuerys)
                    {
                        if (isSubQuery) //子查询DQ不处理SubQuery，否则出现循环引用时会引起堆栈溢出
                            break;
                        //注意不要引起堆栈溢出
                        if (!string.IsNullOrEmpty(subquery.SubQueryID))
                        {
                            if (subquery.SubQuery == null)
                            {
                                subquery.SubQuery = GetMetaDataLocal<DataQuery>(subquery.SubQueryID);
                                //填充子查询DO的实体
                                InitializeDQ(subquery.SubQuery, true, isGetFromDB);
                                if (subquery.SubQuery == null)
                                {
                                }
                            }
                        }
                    }
                } 
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DQ.InitError, $"{unifyCode}初始化失败，请检查！", e);
            }
        }

        public static void InitAuthControl(bool isHasAuth = false, bool sysSwitch = false)
        {
            Maskservice.StartLiveDebug(sysSwitch, !isHasAuth);
            LiveDebug.IsDebug = true;
            if (isHasAuth)
            {
                LiveDebug.IsAllAuth = true;
                LiveDebug.IsNoAuth = false;
            }
            else
            {
                LiveDebug.IsAllAuth = false;
                LiveDebug.IsNoAuth = true;
            }
            LiveDebugService.Start(LiveDebugMode.Mock);
            LiveDebugService.RegisterConfig("Fas.Base.EnableMaskStorage", "false");
            //LiveDebugService.RegisterConfig("BIZ.SYS.GlobalMask", "{\"Switch\":" + sysSwitch.ToString().ToLower() + ",\"SecretKey\":\"xxx\"}");
            //LiveDebugService.RegisterConfig("BIZ.SYS.DesensitizationConfig", "[{\"Type\":\"PhoneNumber\",\"Description\":\"手机号掩码\",\"Pattern\":\"(\\\\d{3})\\\\d{4}(\\\\d{4})\",\"Replacement\":\"$1***$2\"},{\"Type\":\"Email\",\"Description\":\"邮箱掩码\",\"Pattern\":\"(?<=^[\\\\w]{1,10})[\\\\w-\\\\._\\\\+%]*(?=@)\",\"Replacement\":\"**\"},{\"Type\":\"RealName\",\"Description\":\"姓名或昵称掩码\",\"Pattern\":\"(\\\\w)\\\\w* (\\\\w)\\\\w*\",\"Replacement\":\"$1*\"},{\"Type\":\"BankCardNumber\",\"Description\":\"银行卡号掩码\",\"Pattern\":\"(\\\\d{4})(\\\\d{4})(\\\\d{4})(\\\\d{4})\",\"Replacement\":\"$1 $1 ****\"},{\"Type\":\"IdNumber\",\"Description\":\"身份证号掩码\",\"Pattern\":\"\\\\d.*(?=\\\\d{4})\",\"Replacement\":\"*****\"},{\"Type\":\"Address\",\"Description\":\"地址掩码\",\"Pattern\":\"(\\\\w{4})(\\\\w*)\",\"Replacement\":\"$1****\"},{\"Type\":\"Common\",\"Description\":\"通用掩码\",\"Pattern\":\"(?<=^.).*(?=.$)\",\"Replacement\":\"****\"}]");
        }
    }
}
